
import {CanvasHelper} from '../canvas_helper'
import {Vector} from '../vector'

//画图过程中缓存数据, 并实现拖动等基础方法。
class FamilyTreeDrawCache {
  constructor() {
    this.width = 0  //画布的宽
    this.height = 0  //画布的高
    this.offset = new Vector(0, 0)  //当前偏移
    this.scale = 1.5   //放大参数

    this.drag_init_locate = new Vector(0, 0)  //单指拖拽起点缓存
    this.drag_init_offset = new Vector(0, 0)  //单指拖拽开始时的offset
    this.scaling_init_distance = 0  //双指操作初始距离
    this.scaling_init_center = new Vector(0, 0)  //双指操作开始时的中心点
    this.scaling_init_center_pos = new Vector(0, 0)
    this.scaling_init_scale = 1  //双指开始操作时的scale
  }

  //将一个坐标转化为带位移的坐标, 入参和出参均为Vector
  ConvertPosition(pos_vec) {
    return pos_vec.Copy().Scale(this.scale).Add(this.offset)
  }

  //将屏幕坐标反转为position坐标
  ReconvertPosition(screen_vec) {
    return screen_vec.Copy().Sub(this.offset).Scale(1 / this.scale);
  }

  //将一个距离转化为考虑放大参数的距离
  ConvertDistance(distance) {
    return distance * this.scale
  }

  //将屏幕距离反转为坐标距离
  ReconvertDistance(screen_distance) {
    return screen_distance / this.scale
  }
}

//家族树绘制类
class FamilyTreeDrawerBase {
  constructor() { 
    this.ctx = null
    this.drawer = new CanvasHelper() //画图帮助类
    this.cache = new FamilyTreeDrawCache()  //所有缓存的数据
  }

  SetContext(ctx, width, height) {
    //设置画布和画布的整体大小
    this.ctx = ctx
    this.drawer.SetContext(ctx)
    let cache = this.cache
    cache.width = width
    cache.height = height
    cache.position = new Vector(cache.width / 4, cache.height / 4)
  }

  //单指拖拽回调
  OnDragStart(e) {
    //相对于画布内部的屏幕坐标
    let canvasX = e.touches[0].clientX - e.currentTarget.offsetLeft
    let canvasY = e.touches[0].clientY - e.currentTarget.offsetTop
    let cache = this.cache
    cache.drag_init_locate.Set(canvasX, canvasY)
    cache.drag_init_offset.Set(cache.offset)

    this.TapDownCallback(cache.ReconvertPosition(new Vector(canvasX, canvasY)))
  }
  OnDragging(e) {
    let cache = this.cache
    if (!cache.drag_init_locate.IsZero()) {
      let canvasX = e.touches[0].clientX - e.currentTarget.offsetLeft
      let canvasY = e.touches[0].clientY - e.currentTarget.offsetTop
      cache.offset.Set(cache.drag_init_offset.Copy().Add(new Vector(canvasX, canvasY).Sub(cache.drag_init_locate)))

      this.TapMoveCallback(cache.ReconvertPosition(new Vector(canvasX, canvasY)))
    }
  }
  OnDragEnd(e) {
    let cache = this.cache
    cache.drag_init_locate = new Vector(0, 0) 
    cache.drag_init_offset = new Vector(0, 0)

    let canvasX = e.changedTouches[0].clientX - e.currentTarget.offsetLeft
    let canvasY = e.changedTouches[0].clientY - e.currentTarget.offsetTop
    this.TapUpCallback(cache.ReconvertPosition(new Vector(canvasX, canvasY)))
  }

  //双指放大/缩小回调
  OnScaleStart(e) {
    //双指出现先取消单指
    let cache = this.cache
    cache.drag_init_locate = new Vector(0, 0) 
    cache.drag_init_offset = new Vector(0, 0)
    this.DoubleTapStartCallback()

    //
    let canvas0X = e.touches[0].clientX - e.currentTarget.offsetLeft
    let canvas0Y = e.touches[0].clientY - e.currentTarget.offsetTop
    let canvas1X = e.touches[1].clientX - e.currentTarget.offsetLeft
    let canvas1Y = e.touches[1].clientY - e.currentTarget.offsetTop

    //初始距离
    let xMove = canvas1X - canvas0X
    let yMove = canvas1Y - canvas0Y
    cache.scaling_init_distance = Math.sqrt(xMove * xMove + yMove * yMove);  

    //初始scale
    cache.scaling_init_scale = cache.scale

    //放大/缩小的原点
    cache.scaling_init_center = new Vector((canvas1X + canvas0X) / 2, (canvas1Y + canvas0Y) / 2)
    cache.scaling_init_center_pos = cache.ReconvertPosition(cache.scaling_init_center)
  }
  OnScaling(e) {
    let cache = this.cache
    if (cache.scaling_init_distance > 0) {
      let canvas0X = e.touches[0].clientX - e.currentTarget.offsetLeft
      let canvas0Y = e.touches[0].clientY - e.currentTarget.offsetTop
      let canvas1X = e.touches[1].clientX - e.currentTarget.offsetLeft
      let canvas1Y = e.touches[1].clientY - e.currentTarget.offsetTop

      let xMove = canvas1X - canvas0X
      let yMove = canvas1Y - canvas0Y
      let distance = Math.sqrt(xMove * xMove + yMove * yMove)   
      let distanceDiff = distance - cache.scaling_init_distance
      let newScale = cache.scaling_init_scale + 0.002 * distanceDiff

      // 为了防止缩放得太大，所以scale需要限制，同理最小值也是 
      if (newScale >= 3) {
        newScale = 3
      }
      if (newScale <= 0.8) {
        newScale = 0.8
      }
      cache.scale = newScale
      let newPos = cache.ConvertPosition(cache.scaling_init_center_pos)
      //让newPos和scaling_init_center重合
      cache.offset.Sub(newPos.Sub(cache.scaling_init_center))
      
    }
  }
  OnScaleEnd(e) {
    let cache = this.cache
    cache.scaling_init_distance = 0
    cache.scaling_init_center = new Vector(0, 0)
    cache.scaling_init_center_pos = new Vector(0, 0)
    cache.scaling_init_scale = 1 
  }
}

module.exports = {
  FamilyTreeDrawerBase
}